
;
(function($, $$) {

    function Interaction(self, options) {
        var defaults = {

            disable : false,

            getUserMask : null,

            originMask : false,

            stopMouseDownPropagation : false,


            start : false,

            originClientX : 0,

            originClientY : 0,

            doing : false,

            type : null,

            mask : null,

            event : {start : null, doing : null, stop : null},

            maskHTML : '<div class="uiInteractionMask uiInactive uiCornerAll uiBlackBigBorder"></div>'
        };
        var interactionObj = this;
        interactionObj.jqObj = self;
        var opts = interactionObj.opts = {};
        $.extend(opts, defaults, options);
        opts.widgetKey = $$.getRandomKey();
        return interactionObj;
    }

    Interaction.prototype = {

        init : function(self, options) {
            var interactionObj = this;
            var opts = options, obj;
            if (opts.type === "resize") {
                obj = self.find(".uiResizable");
                if (obj.length === 0) {
                    if (self.css("position") === "static") {
                        self.css("position", "relative");
                    }
                    obj = $('<div class="uiResizable"></div>').appendTo(self);
                }
            }
            else
            if (opts.type === "drag") {
                obj = self.find(".uiDraggable");
                if (obj.length === 0) {
                    obj = self.addClass("uiDraggable");
                }
            }
            var mouseDownEvent = "mousedown." + opts.type;
            obj.bind(mouseDownEvent, function(e) {
                setInteractionSetting(self, opts, e);
                if (opts.type == "resize") {
                    return false;
                }
                return !opts.stopMouseDownPropagation;
            });
            var mouseMoveEvent = "mousemove." + opts.widgetKey + opts.type;
            var mouseUpEvent = "mouseup." + opts.widgetKey + opts.type;
            $(document).bind(mouseMoveEvent, function(e) {
                if (opts.start) {
                    if (opts.mask === null) {
                        if (setInteractionMask(self, opts, e) === false) {
                            return;
                        }
                    }
                    var maskItem = opts.mask;
                    opts.doing = true;
                    var offsetX = e.clientX - opts.originClientX, offsetY = e.clientY - opts.originClientY;
                    if (opts.type === "resize") {
                        var newWidth = opts.originWidth + offsetX;
                        var newHeight = opts.originHeight + offsetY;
                        if (opts.maxWidth !== null) {
                            if (newWidth > opts.maxWidth) {
                                newWidth = opts.maxWidth;
                            }
                        }
                        if (opts.minWidth !== null) {
                            if (newWidth < opts.minWidth) {
                                newWidth = opts.minWidth;
                            }
                        }
                        if (opts.maxHeight !== null) {
                            if (newHeight > opts.maxHeight) {
                                newHeight = opts.maxHeight;
                            }
                        }
                        if (opts.minHeight !== null) {
                            if (newHeight < opts.minHeight) {
                                newHeight = opts.minHeight;
                            }
                        }
                        if ($.isFunction(opts.event.doing)) {
                            if (opts.event.doing.call(self[0], maskItem, newWidth, newHeight) === false) {
                                return;
                            }
                        }
                        maskItem.width(newWidth).height(newHeight);
                    }
                    else
                    if (opts.type = "drag") {
                        var position = {left : opts.originPosition.left + offsetX, top : opts.originPosition.top + offsetY};
                        if ($.isFunction(opts.event.doing)) {
                            if (opts.event.doing.call(self[0], maskItem, {left : position.left, top : position.top}) === false) {
                                return;
                            }
                        }
                        maskItem.css({left : position.left, top : position.top});
                        if (opts.dest !== null) {
                            if (checkArea(opts, position, opts.destPosition) === true) {
                                if (!opts.firstCross) {
                                    opts.cross.call(self, true);
                                    opts.firstCross = true;
                                }
                            }
                            else {
                                if (opts.firstCross) {
                                    opts.cross.call(self, false);
                                    opts.firstCross = false;
                                }
                            }
                        }
                    }
                    return false;
                }
            })
                .bind(mouseUpEvent, function() {
                    complete(self, opts);
                });
            return interactionObj;
        }
    }

    function complete(self, opts) {
        if (opts.doing === false) {
            opts.start = false;
            return;
        }
        var maskItem = opts.mask;
        opts.start = false;
        opts.doing = false;
        if ($.isFunction(opts.event.stop)) {
            if (opts.type === "resize") {
                if (opts.event.stop.call(self[0], opts.mask, maskItem.width(), maskItem.height()) === false) {
                    return;
                }
            }
            else
            if (opts.type === "drag") {
                var offset = maskItem.position();
                if (opts.event.stop.call(self[0], opts.mask, offset) === false) {
                    return;
                }
            }
        }
        maskItem.remove();
        opts.mask = null;
    }


    function setInteractionSetting(self, opts, e) {
        if (opts.disable) {
            return;
        }
        opts.start = true;
        if ($.isFunction(opts.event.start)) {
            if (opts.event.start.call(self[0]) === false) {
                opts.start = false;
                return false;
            }
        }
        if ($(e.target).hasClass("uiUserBtn")) {
            opts.start = false;
            return false;
        }
    }


    function setInteractionMask(self, opts, e) {
        var maskHeight = self.outerHeight(), maskWidth = self.outerWidth(), maskPosition = self.position();
        opts.originClientX = e.clientX;
        opts.originClientY = e.clientY;
        opts.outerHeight = maskHeight;
        opts.outerWidth = maskWidth;
        opts.originWidth = self.width();
        opts.originHeight = self.height();
        opts.originPosition = opts.position = maskPosition;
        if ($.isFunction(opts.getUserMask)) {
            opts.mask = opts.getUserMask.call(self[0]);
            opts.originPosition = opts.mask.position();
            if (opts.mask.length === 0) {
                opts.mask = null;
                opts.start = false;
                return false;
            }
            else {
                opts.position = opts.mask.position();
            }
        }
        else
        if (opts.originMask) {
            opts.mask = self.clone().css({position : "absolute", left : maskPosition.left, top : maskPosition.top}).appendTo("body");
        }
        else {
            var marginLeftValue = self.css("marginLeft");
            var marginTopValue = self.css("marginTop");
            opts.mask = $(opts.maskHTML).width(maskWidth).height(maskHeight).css({marginLeft : marginLeftValue, marginTop : marginTopValue, left : maskPosition.left, top : maskPosition.top}).hide().addClass("uiBlackBigBorder uiCornerAll").appendTo("body");
        }
        opts.mask.show();
        if (opts.type === "drag" && opts.dest !== null) {
            var dest = $(opts.dest);
            opts.destPosition = [];
            dest.each(function() {
                var obj = $(this);
                var pos = obj.offset();
                var destWidth = obj.width();
                var destHeight = obj.height();
                opts.destPosition.push(
                    {
                        leftTop : [pos.left, pos.top],
                        rightBottom : [pos.left + destWidth, pos.top + destHeight]
                    });
            });
        }
        return true;
    }


    function checkArea(opts, position, destPosition) {
        var left = position.left;
        var top = position.top;
        var right = left + opts.outerWidth;
        var bottom = top + opts.outerHeight;
        var crossFlag = false;
        for (var i = 0, len = destPosition.length; i < len; i++) {
            var pos = destPosition[i];
            if (!((left > pos.rightBottom[0] | right < pos.leftTop[0]) | (bottom < pos.leftTop[1] | top > pos.rightBottom[1]))) {
                crossFlag = true;
                break;
            }
        }
        return crossFlag;
    }


    $.fn.draggable = function(options) {
        var self = this;
        var draggableObj = new $$.Draggable(self, options);
        draggableObj.init(self, draggableObj.opts);
    }

    $$.Draggable = function(self, options) {
        if (!(this instanceof $$.Draggable)) {
            return new $$.Draggable(self, options);
        }
        var draggableObj = this;
        var defaults = {
            dest : null,

            originPosition : null,
            position : null,
            outerWidth : null,
            outerHeight : null,
            destPosition : null,
            firstCross : false,
            type : "drag",
            widgetKey : null,

            cross : null
        };
        options = $.extend({}, defaults, options);
        $$.Draggable.prototype.superClass.call(draggableObj, self, options);
        var opts = draggableObj.opts;
        if (opts.event.stop == null) {
            opts.event.stop = function(mask, offset) {
                if (opts.disabled) {
                    return false;
                }
                if ($.isFunction(opts.dragStop)) {
                    if (opts.dragStop.call(self) === false) {
                        return false;
                    }
                }
                self.moveToPos({position : offset});
            };
        }
    }
    $$.inherit($$.Draggable, Interaction, {
    });

    $.fn.resizable = function(self, options) {
        var self = this;
        var resizableObj = new $$.Resizable(self, options);
        resizableObj.init(self, resizableObj.opts);
    }

    $$.Resizable = function(self, options) {
        if (!(this instanceof $$.Resizable)) {
            return new $$.Resizable(self, options);
        }
        var resizableObj = this;
        var defaults = {
            minWidth : null,
            minHeight : null,
            maxWidth : 0xffff,
            maxHeight : 0xffff,

            originWidth : 0,
            originHeight : 0,
            type : "resize",
            outerWidth : null,
            outerHeight : null,
            destPosition : null,
            widgetKey : null
        };
        options = $.extend({}, defaults, options);
        $$.Resizable.prototype.superClass.call(resizableObj, self, options);
        var opts = resizableObj.opts;
        if (opts.event.stop == null) {
            opts.event.stop = function(mask, width, height) {
                if (opts.disabled) {
                    return false;
                }
                if ($.isFunction(opts.resizeStop)) {
                    if (opts.resizeStop.call(self) === false) {
                        return false;
                    }
                }
                height = Math.min(Math.max(opts.minHeight, height), opts.maxHeight);
                width = Math.min(Math.max(opts.minWidth, width), opts.maxWidth);
                var otherItemHeightTotal = 0, content = self.width(width).height(height).children(".uiContent");
                self.children().each(function() {
                    var obj = $(this);
                    if (!obj.hasClass("uiContent") && !obj.hasClass("uiResizable")) {
                        otherItemHeightTotal += $(this).outerHeight(true);
                    }
                });
                var outerOffset = content.outerHeight(true) - content.height();
                content.height(height - otherItemHeightTotal - outerOffset);
            };
        }
    }
    $$.inherit($$.Resizable, Interaction, {
    });
})(jQuery, BASE);